#include "ObjectDetectThread.h"
#include "commonFunction.h"

DetectThread::DetectThread(std::string classesFile, std::string modelPath, int batchSize, int imgWidth, int imgHeight, float confThreshold, float iouThreshold, bool useGPU, int gpuId, long max_gpu_memory)
{
	this->detector = new YOLOV7(classesFile, modelPath, batchSize, imgWidth, imgHeight, confThreshold, iouThreshold, useGPU, gpuId, max_gpu_memory);
	if(this->detector->getStatus() !=YOLO_NORMAL){
		this->canUse = false;
	}
}

DetectThread::~DetectThread()
{
	delete this->detector;
}

void DetectThread::setSendQueueMap(ShareMap<std::string, ShareQueue<std::vector<Detection>>*> *queueMap)
{
	this->sendQueueMap = queueMap;
}

void DetectThread::setReceiveQueueMap(ShareMap<std::string, ShareQueue<FrameInfo>*> *queueMap)
{
	this->receiveQueueMap = queueMap;
}

bool DetectThread::initilaize(std::string preLoadFile1, std::string preLoadFile2)
{
	std::string current_path = currentPath();
	std::string test1Path = joinPath(current_path, "models", preLoadFile1);
	std::string test2Path = joinPath(current_path, "models", preLoadFile2);
	cv::Mat img;
	img = cv::imread(test1Path, 1);
	std::cout << "Initializing....Testing the object Detection Model once!Please wait!" << std::endl;
	std::vector<Detection> res = this->detector->detect(img);
	img = cv::imread(test2Path, 1);
	std::cout << "Initializing....Testing the object Detection Model once more!Please wait!" << std::endl;
	res = this->detector->detect(img);
	if (this->detector->getStatus() != YOLO_NORMAL) {
		this->canUse = false;
	}
	return this->canUse;
}

bool DetectThread::isAvaliable()
{
	return this->canUse;
}

void DetectThread::process()
{
	this->timestampVector.clear();
	this->channelVector.clear();
	int batchSize = this->receiveQueueMap->size();
	if (batchSize > 0) {
		this->detector->setBatchSize(batchSize);
		if (this->receiveQueueMap->hasData()) {
			while (this->receiveQueueMap->hasNext()) {
				std::pair<std::string, ShareQueue<FrameInfo>*> queuePair = this->receiveQueueMap->next();
				std::string channel = queuePair.first;
				this->channelVector.emplace_back(channel);
				ShareQueue<FrameInfo>* frameQueue = queuePair.second;
				FrameInfo sourceFrameInfo = frameQueue->get();
				if (sourceFrameInfo.times > 0) {
					this->detector->addBatchItem(sourceFrameInfo.frame);
					this->timestampVector.emplace_back(sourceFrameInfo.times);
				}
			}
			if (this->detector->hasItems()>0) {
				std::vector<std::vector<Detection>> results = this->detector->detectBatch();
				for (int i = 0; i < results.size(); i++) {
					std::vector<Detection> res = results[i];
					std::string channel = this->channelVector[i];
					int64_t times = this->timestampVector[i];
					if (this->sendQueueMap->has(channel)) {
						for (int j = 0; j < res.size(); j++) {
							Detection detection = res[j];
							detection.times = times;
							res[j] = detection;
						}
						ShareQueue<std::vector<Detection>>* detectionQueue = this->sendQueueMap->get(channel);
						detectionQueue->put(res);
					}
				}
			}
		}
	}
}
